﻿Namespace EIB.Bus
    Public NotInheritable Class EIBBusAccessModule_FT12Simulator
        Implements IEIBBusAccessModule

        Private _toggleBit As Boolean = 0
        Private _isConnected As Boolean = False

        Public Event LogBusData(reason As EIBBusAccessLogReason, message As String, data As Byte()) Implements IEIBBusAccessModule.LogBusData
        Public Event ReceiveBusData(address As Addressing.EIBAddress, value() As Byte) Implements IEIBBusAccessModule.ReceiveBusData


        Public Function OpenConnection(ParamArray params() As Object) As Boolean Implements IEIBBusAccessModule.OpenConnection
            InitializeBCU()

            _isConnected = True

            Return True
        End Function

        Public Sub CloseConnection() Implements IEIBBusAccessModule.CloseConnection
            _isConnected = False
        End Sub

        Public ReadOnly Property IsConnected As Boolean Implements IEIBBusAccessModule.IsConnected
            Get
                Return _isConnected
            End Get
        End Property


        Public Sub ReadBusData(address As Addressing.EIBGroupAddress) Implements IEIBBusAccessModule.ReadBusData
            Dim msg As New EIB.Bus.EIBBusData_FrameLData(EIB.BusData.EIBBusData_FramePriority.Normal,
                                             address,
                                             7,
                                             0,
                                             EIB.BusData.EIBBusData_FrameACPI_L_Data_Type.Read, New Byte() {0}
                                            )

            SendVariableFrame(msg.BusData)
        End Sub

        Public Sub RespondBusData(address As Addressing.EIBGroupAddress, value As Byte()) Implements IEIBBusAccessModule.RespondBusData
            Dim msg As New EIB.Bus.EIBBusData_FrameLData(EIB.BusData.EIBBusData_FramePriority.Normal,
                                             address,
                                             7,
                                             0,
                                             EIB.BusData.EIBBusData_FrameACPI_L_Data_Type.Response, value
                                            )

            SendVariableFrame(msg.BusData)
        End Sub

        Public Sub WriteBusData(address As Addressing.EIBGroupAddress, value As Byte()) Implements IEIBBusAccessModule.WriteBusData
            Dim msg As New EIB.Bus.EIBBusData_FrameLData(EIB.BusData.EIBBusData_FramePriority.Normal,
                                                         address,
                                                         7,
                                                         0,
                                                         EIB.BusData.EIBBusData_FrameACPI_L_Data_Type.Write, value
                                                        )

            SendVariableFrame(msg.BusData)
        End Sub


        Private Function InitializeBCU() As Boolean
            'Send reset
            Dim data As Byte() = EIB.Bus.FT12.FT12_FrameBase.FT12_Reset
            Log(EIBBusAccessLogReason.OutgoingMessage, data)

            Dim a As Byte = EIB.Bus.FT12.FT12_FrameBase.FT12_ACK
            Log(EIBBusAccessLogReason.IncomingMessage, a)

            data = New Byte() {&H68, &H8, &H8, &H68, &H73, &HA9, &H96, &H18, &H34, &H56, &H78, &HA, &HD6, &H16}
            data = New Byte() {&H68, &H8, &H8, &H68, &H73, &HA9, &H1E, &H12, &H34, &H56, &H78, &H9A, &HE8, &H16}
            Log(EIBBusAccessLogReason.OutgoingMessage, data)

            Log(EIBBusAccessLogReason.IncomingMessage, a)

            data = New Byte() {&H68, &H6, &H6, &H68, &H53, &HA6, &H1, &H1, &H16, &H0, &H11, &H16}
            data = New Byte() {&H68, &H8, &H8, &H68, &H53, &HA9, &H0, &H18, &H34, &H56, &H78, &HA, &H20, &H16}
            Log(EIBBusAccessLogReason.OutgoingMessage, data)

            Log(EIBBusAccessLogReason.IncomingMessage, a)

            _toggleBit = 0

            Return True
        End Function

        Private Sub SendFixedFrame(primaryMessage As Boolean, messageCode As Byte)
            Dim ft12 As EIB.Bus.FT12.FT12_FrameFixed

            If primaryMessage Then
                _toggleBit = Not _toggleBit

                ft12 = New EIB.Bus.FT12.FT12_FrameFixed(EIB.Bus.FT12.FT12_FrameDirection.PCtoBAU,
                                                        _toggleBit,
                                                        True,
                                                        messageCode
                                                       )
            Else
                ft12 = New EIB.Bus.FT12.FT12_FrameFixed(EIB.Bus.FT12.FT12_FrameDirection.PCtoBAU,
                                                        False,
                                                        messageCode
                                                       )
            End If

            WritePort(ft12.BusData)
        End Sub

        Private Sub SendVariableFrame(data As Byte())
            _toggleBit = Not _toggleBit

            Dim ft12 As New EIB.Bus.FT12.FT12_FrameVariable(EIB.Bus.FT12.FT12_FrameDirection.PCtoBAU,
                                                            _toggleBit,
                                                            True,
                                                            EIB.Bus.FT12.FT12_FramePrimaryMessageCode.SEND_UDAT,
                                                            data
                                                           )

            WritePort(ft12.BusData)
        End Sub

        Private Function ResetBCU() As Boolean Implements IEIBBusAccessModule.ResetBCU
            'Send reset
            Dim data As Byte() = EIB.Bus.FT12.FT12_FrameBase.FT12_Reset
            Log(EIBBusAccessLogReason.OutgoingMessage, data)

            Dim a As Byte = EIB.Bus.FT12.FT12_FrameBase.FT12_ACK
            Log(EIBBusAccessLogReason.IncomingMessage, a)

            Return True
        End Function

        Public Sub GetLinkStatus() Implements IEIBBusAccessModule.GetLinkStatus
            Dim data As Byte() = New Byte() {EIB.Bus.FT12.FT12_FrameBase.FT12_STARTFIXED, &H49, &H49, EIB.Bus.FT12.FT12_FrameBase.FT12_END}
            Log(EIBBusAccessLogReason.OutgoingMessage, data)

            data = New Byte() {EIB.Bus.FT12.FT12_FrameBase.FT12_STARTFIXED, &H49, &H49, EIB.Bus.FT12.FT12_FrameBase.FT12_END}
            Log(EIBBusAccessLogReason.IncomingMessage, data)
        End Sub

        Private Sub WritePort(data As Byte())
            Log(EIBBusAccessLogReason.OutgoingMessage, data)
            Log(EIBBusAccessLogReason.IncomingMessage, EIB.Bus.FT12.FT12_FrameBase.FT12_ACK)
        End Sub


        Private Sub Log(reason As EIBBusAccessLogReason, data As Byte())
            RaiseEvent LogBusData(reason, EIB.Helper.ConvertByteArrayToHexString(data), data)
        End Sub

        Private Sub Log(reason As EIBBusAccessLogReason, data As Byte)
            RaiseEvent LogBusData(reason, EIB.Helper.ConvertByteToHexString(data), New Byte() {data})
        End Sub

        Private Sub Log(reason As EIBBusAccessLogReason, message As String)
            RaiseEvent LogBusData(reason, message, Nothing)
        End Sub
    End Class
End Namespace